return {
  "hrsh7th/nvim-cmp",
  dependencies = {
    "hrsh7th/cmp-nvim-lsp",
    "hrsh7th/cmp-buffer",
    "hrsh7th/cmp-path",
    "hrsh7th/cmp-cmdline",
    "hrsh7th/cmp-nvim-lua",
    "tzachar/cmp-tabnine",
    "lukas-reineke/cmp-under-comparator",
    "L3MON4D3/LuaSnip",
    "saadparwaiz1/cmp_luasnip",
    "windwp/nvim-autopairs",
    "windwp/nvim-autopairs",
  },
  config = function()
    local has_word_before = function()
      unpack = unpack or table.unpack
      local line, col = unpack(vim.api.nvim_win_get_cursor(0))
      return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
    end

    -- require('luasnip.loaders.from_vscode').lazy_load({paths = "./my_snippets"})
    local cmp = require("cmp")
    local luasnip = require("luasnip")

    local tabnine = require("cmp_tabnine.config")
    tabnine:setup({
      max_lines = 1000,
      max_num_results = 10,
      sort = true,
      run_on_every_keystrocke = true,
      snippet_placeholder = "..",
      show_prediction_strength = true
    })

    cmp.setup({
      snippet = {
        expand = function(args)
          luasnip.lsp_expand(args.body)
        end
      },
      -- sorting = {
      --   comparators = {
      --     cmp.config.compare.score,
      --     cmp.config.compare.offset,
      --     cmp.config.compare.exact,
      --     require("cmp-under-comparator").under,
      --     cmp.config.compare.kind,
      --     cmp.config.compare.sort_text,
      --     cmp.config.compare.length,
      --     cmp.config.compare.order,
      --     require('cmp_tabnine.compare')
      --   }
      -- },
      sources = {
        { name = "nvim_lsp" },
        { name = "luasnip" },
        { name = "buffer" },
        { name = "path" },
        { name = "cmp_tabnine" },
      },
      mapping = {
        ['<TAB>'] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_next_item()
          elseif luasnip.expand_or_locally_jumpable() then
            luasnip.expand_or_jump()
          elseif has_word_before() then
            cmp.complete()
          else
            fallback()
          end
        end, { "i", "s", "c" }),
        ['<S-TAB>'] = cmp.mapping(function(fallback)
          if cmp.visible() then
            cmp.select_prev_item()
          elseif luasnip.jumpable(-1) then
            luasnip.jump(-1)
          else
            fallback()
          end
        end, { "i", "s", "c" }),
        ['<C-space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
        ['<C-d>'] = cmp.mapping({
          i = cmp.mapping.abort(),
          c = cmp.mapping.close(),
        }),
        ['<CR>'] = cmp.mapping.confirm({
          select = false
        }),
        ['<C-k>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
        ['<C-j>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
      },
      formatting = {
        fields = { "abbr", "kind", "menu" },
        format = function(entry, vim_item)
          local icons = require("plugins.servers.kinds")
          vim_item.kind = string.format("%s %s", icons[vim_item.kind] or "   ", vim_item.kind)

          vim_item.menu = ({
            buffer = "[Buf]",
            nvim_lsp = "[Lsp]",
            path = "[Path]",
            luasnip = "[Snip]",
            cmp_tabnine = "[Tabnine]",
          })[entry.source.name]

          return vim_item
        end
      },
      experimental = {
        ghost_text = false,
      },
    })

    cmp.setup.cmdline("/", {
      mappings = {
        ["<TAB>"] = cmp.select_next_item(),
        ["<S-TAB>"] = cmp.select_prev_item()
      },
      sources = {
        { name = "buffer" }
      }
    })

    cmp.setup.cmdline(":", {
      mappings = cmp.mapping.preset.cmdline(),
      sources = cmp.config.sources({
        { name = "path" }
      }, {
        { name = "cmdline" }
      })
    })

    require "nvim-autopairs".setup {}
    local cmp_autopairs = require("nvim-autopairs.completion.cmp")
    cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done({ map_char = { tex = "" } }))

    -- gray
    vim.cmd("highlight! CmpItemAbbrDeprecated guibg=NONE gui=strikethrough guifg=#808080")
    -- blue
    vim.cmd("highlight! CmpItemAbbrMatch guibg=NONE guifg=#569CD6")
    vim.cmd("highlight! CmpItemAbbrMatchFuzzy guibg=NONE guifg=#569CD6")
    -- light blue
    vim.cmd("highlight! CmpItemKindVariable guibg=NONE guifg=#9CDCFE")
    vim.cmd("highlight! CmpItemKindInterface guibg=NONE guifg=#9CDCFE")
    vim.cmd("highlight! CmpItemKindText guibg=NONE guifg=#9CDCFE")
    -- pink
    vim.cmd("highlight! CmpItemKindFunction guibg=NONE guifg=#C586C0")
    vim.cmd("highlight! CmpItemKindMethod guibg=NONE guifg=#C586C0")
    -- front
    vim.cmd("highlight! CmpItemKindKeyword guibg=NONE guifg=#D4D4D4")
    vim.cmd("highlight! CmpItemKindProperty guibg=NONE guifg=#D4D4D4")
    vim.cmd("highlight! CmpItemKindUnit guibg=NONE guifg=#D4D4D4")
  end
}
